/**
 * Copyright @ 2000 ysten Co. Ltd. 
 * All right reserved.     
 * @author: wangmin
 * date: 2016-08-02     
 */
package com.task.service.impl;

import com.task.bean.*;
import com.task.entity.SysConfig;
import com.task.entity.User;
import com.task.repository.ISysConfigRepository;
import com.task.repository.IUserRepository;
import com.task.service.IWxService;
import com.task.utils.*;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 微信服务
 */
@Service
public class WxServiceImpl implements IWxService {

    private static final Logger LOGGER = LoggerFactory.getLogger(WxServiceImpl.class);
    public static final String TUFA_APP_ID = "tufaAppId";
    public static final String CORPID = "CORPID";
    public static final String CODE = "CODE";
    public static final String USERID = "USERID";
    public static final String CORPSECRET = "CORPSECRET";

    @Autowired
    ISysConfigRepository sysConfigRepository;

    @Autowired
    IUserRepository userRepository;

    @Override
    public SysConfig getTokenTimestamp() {
        return sysConfigRepository.findByName(Constants.TIMESTAMP);
/*        if(sysConfig == null){
            return null;
        } else {
            return sysConfig.getValue();
        }*/
    }

    @Override
    public JsTokenBean saveAndGetAuthorityInfo(String url) throws Exception {

        JsTokenBean jsTokenBean = new JsTokenBean();
        //1、先获取timestap，判断是否超过7200秒
        SysConfig timestampConfig = getTokenTimestamp();
        String timestamp = timestampConfig.getValue();
        String tokenUrl = PropertiesUtil.getProperty(Constants.TOKEN_URL);
        String jsTicketUrl = PropertiesUtil.getProperty(Constants.JSAPITICKET_URL);
        String nonceStr = StringUtil.getRandomCode();//生成随机字符串
        String nowTimeStr = String.valueOf(System.currentTimeMillis()).substring(0, 10);
        String token;
        String jsTicket = "";
        String signature;
        Long time = Long.parseLong(nowTimeStr) - Long.parseLong(timestamp);//算出相差多少秒
        if (time > Constants.MAXSECONDS) {//大于7200，重新获取token和jsTicket
            timestampConfig.setValue(nowTimeStr);
            sysConfigRepository.save(timestampConfig);

            SysConfig jsTimestampConfig = sysConfigRepository.findByName(Constants.JS_TIMESTAMP);//保存js过期时间
            if (jsTimestampConfig != null) {
                jsTimestampConfig.setValue(nowTimeStr);
            } else {
                jsTimestampConfig = new SysConfig();
                jsTimestampConfig.setName(Constants.JS_TIMESTAMP);
                jsTimestampConfig.setValue(nowTimeStr);
            }
            sysConfigRepository.save(jsTimestampConfig);//保存jsTicket的时间戳

            //获取token
            token = getToken(tokenUrl);
            if (StringUtils.isNotBlank(token)) {
                //获取jsticket
                jsTicket = getJsTicket(jsTicketUrl, token);
            }
            timestamp = nowTimeStr;
        } else { //没有超过7200,
            SysConfig tokenConfig = sysConfigRepository.findByName(Constants.ACCESS_TOKEN);
            SysConfig jsTicketConfig = sysConfigRepository.findByName(Constants.JS_TICKET);
            SysConfig jsTimestampConfig = sysConfigRepository.findByName(Constants.JS_TIMESTAMP);
            if (jsTicketConfig != null) {
                if (jsTimestampConfig != null) {//判断时间是否超时
                    Long time1 = Long.parseLong(nowTimeStr) - Long.parseLong(jsTimestampConfig.getValue());
                    if (time1 > Constants.MAXSECONDS) {//超时
                        jsTicket = getJsTicket(jsTicketUrl, tokenConfig.getValue());
                        jsTimestampConfig.setValue(nowTimeStr);
                        sysConfigRepository.save(jsTimestampConfig);
                    } else {//未超时
                        jsTicket = jsTicketConfig.getValue();
                    }
                } else {
                    jsTimestampConfig = new SysConfig();
                    jsTimestampConfig.setName(Constants.JS_TIMESTAMP);
                    jsTimestampConfig.setValue(nowTimeStr);
                    sysConfigRepository.save(jsTimestampConfig);
                    jsTicket = getJsTicket(jsTicketUrl, tokenConfig.getValue());
                }
            } else {
                jsTicket = getJsTicket(jsTicketUrl, tokenConfig.getValue());
                if (jsTimestampConfig != null) {
                    jsTimestampConfig.setValue(nowTimeStr);
                } else {
                    jsTimestampConfig = new SysConfig();
                    jsTimestampConfig.setName(Constants.JS_TIMESTAMP);
                    jsTimestampConfig.setValue(nowTimeStr);
                }
                sysConfigRepository.save(jsTimestampConfig);
            }
        }
        if (StringUtils.isNotBlank(jsTicket)) {
            String str = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
            signature = EncodeUtils.sha1Encode(str);//生成签名
            jsTokenBean.setAppId(PropertiesUtil.getProperty(Constants.CORPID));
            jsTokenBean.setNonceStr(nonceStr);
            jsTokenBean.setTimestamp(timestamp);
            jsTokenBean.setSignature(signature);
            return jsTokenBean;
        }
        return jsTokenBean;
    }

    @Override
    public String saveWxUserInfo(String code) {
        SysConfig timestampConfig = getTokenTimestamp();
        String timestamp = null;
        if (timestampConfig != null) {
            timestamp = timestampConfig.getValue();
        }
        String tokenUrl = PropertiesUtil.getProperty(Constants.TOKEN_URL);
        String getUserInfoUrl = PropertiesUtil.getProperty(Constants.GET_USERINFO_URL);
        String getDetailUserInfoUrl = PropertiesUtil.getProperty(Constants.GET_DETAIL_USERINFO_URL);
        String nowTimeStr = String.valueOf(System.currentTimeMillis()).substring(0, 10);
        String token = null;
        if (StringUtils.isBlank(timestamp)) {//未初始化
            SysConfig sysConfig = new SysConfig();
            sysConfig.setName(Constants.TIMESTAMP);
            sysConfig.setValue(nowTimeStr);
            sysConfigRepository.save(sysConfig);
            token = getToken(tokenUrl);
        } else {
            Long time = Long.parseLong(nowTimeStr) - Long.parseLong(timestamp);//算出相差多少秒
            if (time > Constants.MAXSECONDS) {//大于7200，重新获取token
                token = getToken(tokenUrl);
                timestampConfig.setValue(nowTimeStr);
                sysConfigRepository.save(timestampConfig);
            } else { //没有超过7200,直接使用
                SysConfig tokenConfig = sysConfigRepository.findByName(Constants.ACCESS_TOKEN);
                if (tokenConfig != null) {
                    token = tokenConfig.getValue();
                }
            }
        }
        if (StringUtils.isNotBlank(token)) {
            getUserInfoUrl = getUserInfoUrl.replace(Constants.ACCESS_TOKEN_KEY, token).replace(CORPID, PropertiesUtil.getProperty(Constants.CORPID)).replace(CODE, code);
            String userInfoResult = HttpsUtils.get(getUserInfoUrl);
            if (StringUtils.isNotBlank(userInfoResult)) {
                JSONObject userObj = JsonUtils.fromJson(userInfoResult, JSONObject.class);
                if (userObj != null && userObj.get("UserId") != null) {
                    String userId = (String) userObj.get("UserId");
                    getDetailUserInfoUrl = getDetailUserInfoUrl.replace(Constants.ACCESS_TOKEN_KEY, token).replace(USERID, userId);
                    String detailUserInfoResult = HttpsUtils.get(getDetailUserInfoUrl);
                    if (StringUtils.isNotBlank(detailUserInfoResult)) {
                        LOGGER.info("detailUserInfoResult,:{}", detailUserInfoResult);
                        CorpUserDetailInfo corpUserDetailInfo = JsonUtils.fromJson(detailUserInfoResult, CorpUserDetailInfo.class);
//                        LOGGER.info(new GsonBuilder().create().toJson(corpUserDetailInfo));
                        if (StringUtils.equals(corpUserDetailInfo.getErrcode(), "0")) {
                            User user = userRepository.findByUserId(corpUserDetailInfo.getUserid());
                            if (user == null) {//没有，新增,有,更新
                                user = new User();
                                user.setUserId(corpUserDetailInfo.getUserid());

                                //获取openID
                                String openId = getOpenIdByUserId(corpUserDetailInfo.getUserid(), token);
                                if (StringUtils.isNotBlank(openId)) {
                                    user.setOpenId(openId);
                                }
                            }
                            //获取所属部门
                            String departmentName = "";
                            DepartmentInfo departmentInfo;
                            if (!CollectionUtils.isEmpty(corpUserDetailInfo.getDepartment())) {
                                for (Integer departmentId : corpUserDetailInfo.getDepartment()) {
                                    departmentInfo = getDepartmentInfo(departmentId, token);
                                    if (departmentInfo != null) {
                                        departmentName += departmentInfo.getName() + ",";
                                    }
                                }
                            }
                            if (StringUtils.isNotBlank(departmentName)) {
                                user.setDepartment(StringUtils.substring(departmentName, 0, departmentName.length() - 1));
                            }
                            user.setStatus(corpUserDetailInfo.getStatus());
                            user.setAvatar(corpUserDetailInfo.getAvatar());
                            user.setEmail(corpUserDetailInfo.getEmail());
                            user.setGender(corpUserDetailInfo.getGender());
                            user.setMobile(corpUserDetailInfo.getMobile());
                            user.setName(corpUserDetailInfo.getName());
                            user.setPosition(corpUserDetailInfo.getPosition());
                            user.setWeixinid(corpUserDetailInfo.getWeixinid());

                            //保存用户信息
                            userRepository.save(user);
                            return corpUserDetailInfo.getUserid();
                        } else {
                            LOGGER.error("get user detail info error");
                        }
                    }
                }
            }
        }
        return "";
    }

    /**
     * 查询部门信息
     *
     * @param departmentId
     * @param accessToken
     * @return
     */
    private DepartmentInfo getDepartmentInfo(Integer departmentId, String accessToken) {
        String getUserInfoUrl = PropertiesUtil.getProperty(Constants.GET_DEPARTMENT_URL);
        getUserInfoUrl = getUserInfoUrl.replace(Constants.ACCESS_TOKEN_KEY, accessToken).replace(Constants.IDKEY, String.valueOf(departmentId));
        String departmentInfoResult = HttpsUtils.get(getUserInfoUrl);
        if (StringUtils.isNotBlank(departmentInfoResult)) {
            LOGGER.info("departmentInfoResult,:{}", departmentInfoResult);
            DepartmentResult departmentResult = JsonUtils.fromJson(departmentInfoResult, DepartmentResult.class);
            if (StringUtils.equals(departmentResult.getErrcode(), "0")) {
                List<DepartmentInfo> departmentInfoList = departmentResult.getDepartment();
                if (!CollectionUtils.isEmpty(departmentInfoList)) {
                    return departmentInfoList.get(0);
                }
            } else {
                LOGGER.error("get department info error");
            }
        }
        return null;

    }

    /**
     * 根据userId、token查询openId
     *
     * @param userId
     * @param token
     * @return
     */
    private String getOpenIdByUserId(String userId, String token) {
        String getOpenIdByUserIdUrl = PropertiesUtil.getProperty(Constants.GET_OPENID_URL);//查询openId url
        if (StringUtils.isNotBlank(getOpenIdByUserIdUrl)) {
            getOpenIdByUserIdUrl = getOpenIdByUserIdUrl.replace(Constants.ACCESS_TOKEN_KEY, token);
            JSONObject requestBody = new JSONObject();
            requestBody.put(Constants.USERID, userId);
            requestBody.put(Constants.AGENTID, PropertiesUtil.getProperty(TUFA_APP_ID));
            String result = HttpsUtils.post(getOpenIdByUserIdUrl, requestBody.toString());
            if (StringUtils.isNotBlank(result)) {
                JSONObject resultObj = JsonUtils.fromJson(result, JSONObject.class);
                if (resultObj != null && resultObj.get(Constants.OPENID) != null) {
                    return (String) resultObj.get(Constants.OPENID);
                }
            }
        }
        return null;
    }

    /**
     * 获取js票据
     *
     * @param jsTicketUrl
     * @param token
     * @return
     */
    private String getJsTicket(String jsTicketUrl, String token) {
        String jsTicket = "";
        if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(jsTicketUrl)) {
            jsTicketUrl = jsTicketUrl.replace(Constants.ACCESS_TOKEN_KEY, token);
            String ticketResult = HttpsUtils.get(jsTicketUrl);
            if (StringUtils.isNotBlank(ticketResult)) {
                JsTicketBean jsTicketBean = JsonUtils.fromJson(ticketResult, JsTicketBean.class);
                if (jsTicketBean != null) {
                    if (StringUtils.isNotEmpty(jsTicketBean.getTicket())) {
                        jsTicket = jsTicketBean.getTicket();

                        SysConfig sysConfig = sysConfigRepository.findByName(Constants.JS_TICKET);
                        if (sysConfig != null) {//更新
                            sysConfig.setValue(jsTicket);
                        } else {//新增
                            sysConfig = new SysConfig();
                            sysConfig.setName(Constants.JS_TICKET);
                            sysConfig.setValue(jsTicket);
                        }
                        sysConfigRepository.save(sysConfig);
//                        PropertiesUtil.setProperty(Constants.JS_TICKET, jsTicket);
                    } else {
                        LOGGER.error("getJsTicket fails," + ticketResult);
                    }
                }
            }
        }
        return jsTicket;
    }

    /**
     * 获取access_token
     *
     * @param tokenUrl
     * @return
     */
    private String getToken(String tokenUrl) {
        String token = "";
        if (StringUtils.isNotBlank(tokenUrl)) {
            tokenUrl = tokenUrl.replace(CORPID, PropertiesUtil.getProperty(Constants.CORPID)).replace(CORPSECRET, PropertiesUtil.getProperty(Constants.CORPSECRET));
            String result = HttpsUtils.get(tokenUrl);
            if (StringUtils.isNotBlank(result)) {
                TokenResult tokenResult = JsonUtils.fromJson(result, TokenResult.class);
                if (tokenResult != null) {
                    if (StringUtils.isNotEmpty(tokenResult.getAccess_token())) {
                        token = tokenResult.getAccess_token();
                        SysConfig sysConfig = sysConfigRepository.findByName(Constants.ACCESS_TOKEN);
                        if (sysConfig != null) {//更新
                            sysConfig.setValue(token);
                        } else {//新增
                            sysConfig = new SysConfig();
                            sysConfig.setName(Constants.ACCESS_TOKEN);
                            sysConfig.setValue(token);
                        }
                        sysConfigRepository.save(sysConfig);
//                        PropertiesUtil.setProperty(Constants.ACCESS_TOKEN, token);
                    } else {
                        LOGGER.error(tokenResult.getErrcode() + ":" + tokenResult.getErrmsg());
                    }
                } else {
                    LOGGER.error("get token error");
                }
            }
        }
        return token;
    }

    @Override
    public String saveAndGetAccessToken() {
        String timestamp = null;
        SysConfig timestampConfig = sysConfigRepository.findByName(Constants.TIMESTAMP);
        if (timestampConfig != null) {
            timestamp = timestampConfig.getValue();
        }
        String tokenUrl = PropertiesUtil.getProperty(Constants.TOKEN_URL);
        String nowTimeStr = String.valueOf(System.currentTimeMillis()).substring(0, 10);
        String token = null;
        Long time = Long.parseLong(nowTimeStr) - Long.parseLong(timestamp);//算出相差多少秒
        if (time > Constants.MAXSECONDS) {//大于7200，重新获取token
            token = getToken(tokenUrl);
            timestampConfig.setValue(nowTimeStr);
            sysConfigRepository.save(timestampConfig);
        } else { //没有超过7200,直接使用
            SysConfig tokenConfig = sysConfigRepository.findByName(Constants.ACCESS_TOKEN);
            if (tokenConfig != null) {
                token = tokenConfig.getValue();
            }
        }
        return token;
    }
}
